package com.bfsoft.springbootinit.service.impl;

import com.bfsoft.springbootinit.config.SystemConfig;
import com.bfsoft.springbootinit.enums.FlowComment;
import com.bfsoft.springbootinit.pojo.dto.IdDTO;
import com.bfsoft.springbootinit.pojo.dto.flow.FlowTaskDto;
import com.bfsoft.springbootinit.pojo.vo.ResultVO;
import com.bfsoft.springbootinit.pojo.vo.TaskVo;
import com.bfsoft.springbootinit.pojo.vo.flow.ProcessDetail;
import com.bfsoft.springbootinit.service.FlowableTestService;
import com.bfsoft.springbootinit.util.FindNextNodeUtil;
import com.bfsoft.springbootinit.util.RestTemplateUtil;
import jakarta.annotation.Resource;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.flowable.bpmn.model.UserTask;
import org.flowable.engine.*;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.task.Comment;
import org.flowable.task.api.DelegationState;
import org.flowable.task.api.Task;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Slf4j
@Service
@Setter ( onMethod_ = @Resource )
public class FlowableTestServiceImpl implements FlowableTestService {

	private RepositoryService repositoryService;

	private RuntimeService runtimeService;

	private IdentityService identityService;

	private TaskService taskService;

	private HistoryService historyService;

	private RestTemplateUtil restTemplateUtil;

	public SystemConfig systemConfig;


	@Override
	@Transactional ( rollbackFor = Exception.class )
	public ResultVO < Object > startProcess ( TaskVo dto ) {
		return restTemplateUtil.postFetchData ( "/procurement/startProcess" , dto  );
	}

	@Override
	@Transactional ( rollbackFor = Exception.class )
	public ResultVO < Object > getStartNextNode ( TaskVo dto ) {
		// 查找流程定义信息
		ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery ()
				.processDefinitionId ( dto.getProcessId () ).latestVersion ().singleResult ();
		if ( Objects.isNull ( processDefinition ) ) {
			return ResultVO.fail ( "流程信息不存在!" );
		}
		// 获取下一任务节点(网关节点时需要校验表达式)
		List < UserTask > nextUserTask = FindNextNodeUtil.getNextUserTasksByStart ( repositoryService ,
				processDefinition , dto.getProcessVariables () );
		if ( CollectionUtils.isEmpty ( nextUserTask ) ) {
			return ResultVO.fail ( "暂未查找到下一任务,请检查流程设计是否正确!" );
		}
		return ResultVO.ok( getNextCandidateGroup ( nextUserTask ) );
	}

	@Override
	public ResultVO < Object > getApprovalNextNode ( TaskVo dto ) {
		// 获取当前节点并找到下一步节点
		Task task = taskService.createTaskQuery ().taskId ( dto.getTaskId () ).singleResult ();
		if ( Objects.isNull ( task ) ) {
			return ResultVO.fail ( "任务不存在或已被审批!" );
		}
		// 获取当前流程所有流程变量(网关节点时需要校验表达式)
		Map < String,Object > variables = taskService.getVariables ( task.getId () );
		List < UserTask > nextUserTask = FindNextNodeUtil.getNextUserTasks ( repositoryService , task , variables );
		if ( CollectionUtils.isEmpty ( nextUserTask ) ) {
			return ResultVO.ok (  null , "流程已完结" );
		}
		return ResultVO.ok( getNextCandidateGroup ( nextUserTask ) );

	}

	@Override
	public ResultVO < Object > myProcessList ( TaskVo dto ) {
		return restTemplateUtil.postFetchData ( "/procurement/myProcessList" , dto  );
	}

	@Override
	public ResultVO < Object > myTodoList ( TaskVo dto ) {
		return restTemplateUtil.postFetchData ( "/procurement/myTodoList" , dto  );
	}

	@Override
	@Transactional ( rollbackFor = Exception.class )
	public ResultVO < Object > complete ( TaskVo taskVo ) {
		return restTemplateUtil.postFetchData ( "/procurement/complete" , taskVo  );
	}

	@Override
	public ResultVO < Object > finishedList ( TaskVo dto ) {
		return restTemplateUtil.postFetchData ( "/procurement/finishedList" , dto  );
	}

	@Override
	public ResultVO < Object > getProcessDetail ( TaskVo taskVo ) {
		return restTemplateUtil.postFetchData ( "/procurement/getProcessDetail" , taskVo  );
	}

	@Override
	public ResultVO < Object > getSystemProcessList ( IdDTO dto ) {
		return restTemplateUtil.getListDataById ( "/api/open/process/list/{systemId}" , dto.getId () );
	}


	private List < String > getNextCandidateGroup ( List < UserTask > nextUserTask ) {
		List < String > candidateGroups = new ArrayList <> ();
		for ( UserTask userTask : nextUserTask ) {
			candidateGroups.addAll ( userTask.getCandidateGroups () );
		}
		return candidateGroups;
	}

	/**
	 * 流程完成时间处理
	 */
	private String getDate ( long ms ) {

		long day = ms / ( 24 * 60 * 60 * 1000 );
		long hour = ( ms / ( 60 * 60 * 1000 ) - day * 24 );
		long minute = ( ( ms / ( 60 * 1000 ) ) - day * 24 * 60 - hour * 60 );
		long second = ( ms / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - minute * 60 );

		if ( day > 0 ) {
			return day + "天" + hour + "小时" + minute + "分钟";
		}
		if ( hour > 0 ) {
			return hour + "小时" + minute + "分钟";
		}
		if ( minute > 0 ) {
			return minute + "分钟";
		}
		if ( second > 0 ) {
			return second + "秒";
		}
		else {
			return 0 + "秒";
		}
	}
}
